#pragma once

//@author A0097466M
#include <vector>
#include <time.h>
#include <stack>
#include <stdlib.h>
#include "Parser.h"
#include "Task.h"
#include "Utilities.h"

using namespace std;

class Parser
{

private:
	static const string ERRORMESSAGE_MISSING_BRACKET;
	static const string ERRORMESSAGE_INVALID_TIME;
	static const string ERRORMESSAGE_INVALID_DATE;
	static const string STRING_NEXT;
	static const string STRING_00;
	static const string STRING_12;
	static const string STRING_24;
	static const char CHARACTER_DOT;
	static const char CHARACTER_BACK_SLASH;

	int stringToInt(string);
	string intToString(int);

	//Pre: date in string given does not exist 
	//Post: normalise and return a string of valid date
	string normalizeInvalidDate(string);

	bool compareTime(string, string);

	bool checkStringOfInt(string);
	bool checkStringOfChar(string);

	int numberOfGivenCharacter(string, char);
	int wordCount(string);

	//Pre: nil 
	//Post: vector with months in a year
	static void defaultMonthsInYear(vector<string>&);

	//Pre: nil
	//Post: vector with days of a week
	static void defaultDaysInWeek(vector<string>&);

	//Pre: nil 
	//Post: return true if end time is strictly greater than start time, returns false otherwise
	void processStartAndEndTime(string, string);

	//Pre: nil 
	//Post: process time information in input string and returns a string containing time in 24-hour format
	string processRawTime(string, bool);


	bool timeTypeDefault(string rawTime);
	bool timeType1(string);
	bool timeType2(string);

	//Pre: string containing time in 24-hour format 
	//Post: return valid time in 24-hour format
	string processTimeType1(string);	

	//Pre: string containing time in 12-hour format 
	//Post: return valid time in 12-hour format  
	string processTimeType2(string);

	bool checkValidTime(string);
	int processTimeNotation(string);

	//Pre: nil 
	//Post: process date information in input string and returns a string containing date in DDMMYYYY
	string processRawDate(string);

	bool dateType1(string);
	bool dateType2(string);
	bool dateType3(string);
	bool dateType4(string);

	//Pre: string containing date in DDMMYYYY format 
	//Post: return valid date in DDMMYYYY format
	string processDateType1(string);

	//Pre: string containing date in written format (eg. 11 Nov 2013 or 11 Nov) 
	//Post: return valid date in DDMMYYYY format
	string processDateType2(string);
	string processType2DateWithYear(string);
	string processType2DateWithoutYear(string);

	//Pre: string containing date in DD/MM/YYYY format 
	//Post: return valid date in DDMMYYYY format
	string processDateType3(string);
	string processType3DateWithYear(string);
	string processType3DateWithoutYear(string);

	//Pre: string containing date in written format which require system time (eg. monday, today, tomorrow, next monday) 
	//Post: return valid date in DDMMYYYY format
	string processDateType4(string);
	string dateType4SingleWord(string);
	string dateType4DoubleWord(string);
	string processToday();
	string processTomorrow();
	string processDay(string, bool);
	int diffInDaysWithoutNext(string);
	int diffInDaysWithNext(string);

	string convertMonth(string);

	bool checkValidDate(string);	
	bool checkValidDay(string, string, string);
	bool checkValidMonth(string);
	bool checkValidYear(string);
	int maxNumOfDays(string, string);
	bool checkLeapYear(string);

	string taskExtractDate(Task);

	//Pre: extracts start time in task
	//Post: return time in 24-hour format
	string taskExtractTime1(Task);

	//Pre: extracts end time in task
	//Post: return time in 24-hour format
	string taskExtractTime2(Task);
	string taskExtractDescription(Task);
	string taskExtractTag(Task);	

public:
	Parser(void);
	//Pre: nil
	//Post: returns task with information from input string
	Task parseTask(string);
	//Pre: nil 
	//Post: returns string with information from given task
	string reverseParse(Task);
};

